//
// Created by WINDOWS on 2024/12/31.
//
#include "Calculator.h"

using namespace std;

double Calculator::evaluate(const std::string& expression) {
    this->expression = expression;
    this->pos = 0;
    this->errorInfo = {CalculatorError::None, ""}; // 重置错误信息
    double result = parseExpression();
    return (errorInfo.errorType == CalculatorError::None) ? result : 0; // 返回0或其他值表示出错
}

// parseExpression 方法解析加法和减法。
double Calculator::parseExpression() {
    double result = parseTerm();
    while (pos < expression.size()) {
        char op = expression[pos];
        if (op == '+' || op == '-') {
            pos++;
            double term = parseTerm();
            if (errorInfo.errorType != CalculatorError::None) return 0; // 检查错误
            result = (op == '+') ? result + term : result - term;
        } else {
            break;
        }
    }
    return result;
}

// parseTerm 方法解析乘法、除法和取模运算。
double Calculator::parseTerm() {
    double result = parseFactor();
    while (pos < expression.size()) {
        char op = expression[pos];
        if (op == '*' || op == '/' || op == '%') {
            pos++;
            double factor = parseFactor();
            if (errorInfo.errorType != CalculatorError::None) return 0; // 检查错误
            if (op == '*') {
                result *= factor;
            } else if (op == '/') {
                if (factor == 0) {
                    errorInfo = {CalculatorError::DivisionByZero, "Division by zero"};
                    return 0;
                }
                result /= factor;
            } else if (op == '%') {
                result = static_cast<int>(result) % static_cast<int>(factor);
            }
        } else {
            break;
        }
    }
    return result;
}

// parseFactor 方法处理括号和幂运算
double Calculator::parseFactor() {
    if (pos >= expression.size()) {
        errorInfo = {CalculatorError::UnexpectedEndOfExpression, "Unexpected end of expression"};
        return 0;
    }

    double result;

    if (expression[pos] == '(' || expression[pos] == '{' || expression[pos] == '[') {
        char opening = expression[pos++];
        result = parseExpression();
        if (errorInfo.errorType != CalculatorError::None) return 0; // 检查错误
        if (pos < expression.size() && matchingBracket(opening, expression[pos])) {
            pos++;
        } else {
            errorInfo = {CalculatorError::MismatchedBrackets, "Mismatched brackets"};
            return 0;
        }
    } else {
        result = parseUnary();
    }

    // 处理幂运算
    while (pos < expression.size() && expression[pos] == '^') {
        pos++;
        double exponent = parseFactor();
        if (errorInfo.errorType != CalculatorError::None) return 0; // 检查错误
        result = std::pow(result, exponent);
    }
    return result;
}

// parseUnary 方法处理一元运算符（正负号）。
double Calculator::parseUnary() {
    if (pos < expression.size() && expression[pos] == '-') {
        pos++;
        return -parseUnary();
    }
    if (pos < expression.size() && expression[pos] == '+') {
        pos++;
        return parseUnary();
    }
    return parsePrimary();
}

// parsePrimary 方法处理基本元素，包括数字、绝对值和阶乘。
double Calculator::parsePrimary() {
    if (pos >= expression.size()) {
        errorInfo = {CalculatorError::UnexpectedEndOfExpression, "Unexpected end of expression"};
        return 0;
    }

    if (isdigit(expression[pos])) {
        size_t endPos;
        double value = std::stod(expression.substr(pos), &endPos);
        pos += endPos;
        return value;
    } else if (expression[pos] == '|') {
        pos++;
        double value = parseExpression();
        if (errorInfo.errorType != CalculatorError::None) return 0; // 检查错误
        if (pos < expression.size() && expression[pos] == '|') {
            pos++;
            return std::abs(value);
        } else {
            errorInfo = {CalculatorError::MismatchedBrackets, "Mismatched absolute value"};
            return 0;
        }
    } else if (expression[pos] == '!') {
        pos++;
        double value = parsePrimary();
        if (errorInfo.errorType != CalculatorError::None) return 0; // 检查错误
        return factorial(value);
    }

    errorInfo = {CalculatorError::UnexpectedCharacter, "Unexpected character: " + std::string(1, expression[pos])};
    return 0;
}

// factorial 方法计算给定非负整数的阶乘。
double Calculator::factorial(double n) {
    if (n < 0 || n != static_cast<int>(n)) {
        errorInfo = {CalculatorError::FactorialError, "Factorial of negative or non-integer"};
        return 0;
    }
    double result = 1;
    for (int i = 1; i <= static_cast<int>(n); ++i) {
        result *= i;
    }
    return result;
}

// matchingBracket 方法检查给定的开括号和闭括号是否匹配。
bool Calculator::matchingBracket(char opening, char closing) {
    return (opening == '(' && closing == ')') ||
           (opening == '{' && closing == '}') ||
           (opening == '[' && closing == ']');
}